﻿using CTP.CRM.Core.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp;
using CTP.CRM.Repository.Setting.Services;
using CTP.CRM.Application.Dtos.OAuth;
using CTP.CRM.Core.Common.Constants;
using CTP.CRM.Repository.Enum;
using Bunny;

namespace CTP.CRM.Application.Services.OAuth
{
    public class DataLockedService : IScopedDependency
    {
        private SettingRepository _setting;

        public DataLockedService(SettingRepository setting)
        {
            _setting = setting;
        }

        /// <summary>
        /// 获取锁定信息
        /// </summary>
        /// <param name="dataKey"></param>
        /// <param name="lockedInfo"></param>
        /// <returns>如果锁定了返回true</returns>
        public async Task<(bool, LockedInfo)> TryGetLocked(string dataKey)
        {
            dataKey = GetDataKey(dataKey);

            var lockedInfo = await RedisHelper.Client.GetAsync<LockedInfo>(dataKey);
            if (lockedInfo != null && lockedInfo.LockEndTime > DateTime.Now)
            {
                return (true, lockedInfo);
            }

            return (false, null);
        }

        /// <summary>
        /// 获取锁定信息
        /// </summary>
        /// <param name="dataKey"></param>
        /// <param name="lockedInfo"></param>
        /// <returns>如果锁定了返回true</returns>
        public bool TryGetLocked(string dataKey, out LockedInfo lockedInfo)
        {
            dataKey = GetDataKey(dataKey);
            lockedInfo = RedisHelper.Client.Get<LockedInfo>(dataKey);
            if (lockedInfo != null && lockedInfo.LockEndTime > DateTime.Now)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 添加锁定信息，如果满足锁定条件，返回true，并返回锁定信息
        /// </summary>
        /// <param name="dataKey"></param>
        /// <param name="lockedMsg"></param>
        /// <returns></returns>
        /// <exception cref="BusinessException"></exception>
        public async Task<(bool, string)> AddLocked(string dataKey)
        {
            // get config 
            var lockedConfig = _setting.GetSettingValue<LockedConfiguration>(SystemSettingConstants.DataLockedSettingId, SettingTypeEnum.System);

            if (lockedConfig == null)
            {
                throw new BusinessException("未配置账号重试锁定相关配置");
            }

            bool isLocked = false;
            var lockedMsg = string.Empty;

            /* if the data is not locked
             * 1. if the data is not locked, add a new locked info
             * 2. if the data is locked, check the retry count
             */
            string retryComment = "输错账号密码次数已达{RetryCount}次，次数达到{FirstRetryCount},将锁定{FirstLockTime}分钟";
            string lockingCommentMin = "账号已被锁定{FirstLockTime}分钟";
            string lockingCommentHour = "账号已被锁定{FirstLockTime}小时";
            string retryCode = "login_err_retry";
            string lockingHourCode = "account_locked_hour";
            string lockingMinCode = "account_locked_min";
            var (islock, lockedInfo) = await TryGetLocked(dataKey);
            if (!islock && lockedInfo == null)
            {
                lockedInfo = new LockedInfo
                {
                    RetryCount = 1,
                    LockEndTime = DateTime.Now,
                    LockedCount = 1
                };

                if (lockedInfo.LockedCount == 1)
                {
                    lockedMsg = $"输错账号密码次数已达{lockedInfo.RetryCount}次，次数达到{lockedConfig.FirstRetryCount},将锁定{lockedConfig.FirstLockTime}分钟";
                    //lockedMsg = retryCode.EscapeStringAsync(
                    //    null, BunnyParams.FromObject(new
                    //    {
                    //        RetryCount = lockedInfo.RetryCount,
                    //        FirstRetryCount = lockedConfig.FirstRetryCount,
                    //        FirstLockTime = lockedConfig.FirstLockTime
                    //    })
                    //).GetAwaiter().GetResult();
                }
                else
                {
                    lockedMsg = $"输错账号密码次数已达{lockedInfo.RetryCount}次，次数达到{lockedConfig.SecondRetryCount},将锁定{lockedConfig.SecondLockTime}分钟";
                    //lockedMsg = retryCode.EscapeStringAsync(
                    //    null, BunnyParams.FromObject(new
                    //    {
                    //        RetryCount = lockedInfo.RetryCount,
                    //        FirstRetryCount = lockedConfig.SecondRetryCount,
                    //        FirstLockTime = lockedConfig.SecondLockTime
                    //    })
                    //).GetAwaiter().GetResult();
                }
            }
            else
            {
                lockedInfo.RetryCount++;
                if (lockedInfo.LockedCount == 1 && lockedInfo.RetryCount >= lockedConfig.FirstRetryCount)
                {
                    lockedInfo.LockEndTime = DateTime.Now.AddMinutes(lockedConfig.FirstLockTime);
                     lockedMsg = $"账号已被锁定{lockedConfig.FirstLockTime}分钟";
                    //lockedMsg = lockingMinCode.EscapeStringAsync(
                    //    null, BunnyParams.FromObject(new
                    //    {
                    //        FirstLockTime = lockedConfig.FirstLockTime
                    //    })
                    //).GetAwaiter().GetResult();
                    lockedInfo.RetryCount = 0;
                    lockedInfo.LockedCount++;
                    isLocked = true;
                }
                else if (lockedInfo.RetryCount >= lockedConfig.SecondRetryCount)
                {
                    var lockedTime = TimeSpan.FromMinutes(lockedConfig.SecondLockTime);
                    lockedInfo.LockEndTime = DateTime.Now.Add(lockedTime);
                    lockedInfo.RetryCount = 0;
                    lockedInfo.LockedCount++;

                    if (lockedConfig.SecondLockTime > 60)
                    {
                         lockedMsg = $"账号已被锁定{lockedConfig.SecondLockTime / 60}小时";
                        //lockedMsg = lockingHourCode.EscapeStringAsync(
                        //    null, BunnyParams.FromObject(new
                        //    {
                        //        FirstLockTime = lockedConfig.SecondLockTime / 60
                        //    })
                        //).GetAwaiter().GetResult();

                    }
                    else
                    {
                         lockedMsg = $"账号已被锁定{lockedConfig.SecondLockTime}分钟";
                        //lockedMsg = lockingMinCode.EscapeStringAsync(
                        //    null, BunnyParams.FromObject(new
                        //    {
                        //        FirstLockTime = lockedConfig.FirstLockTime
                        //    })
                        //).GetAwaiter().GetResult();
                    }
                    isLocked = true;
                }

                if (!isLocked)
                {
                    if (lockedInfo.LockedCount == 1)
                    {
                        lockedMsg=$"输错账号密码次数已达{lockedInfo.RetryCount}次，次数达到{lockedConfig.FirstRetryCount},将锁定{lockedConfig.FirstLockTime}分钟";
                        //lockedMsg = retryCode.EscapeStringAsync(
                        //    null, BunnyParams.FromObject(new
                        //    {
                        //        RetryCount = lockedInfo.RetryCount,
                        //        FirstRetryCount = lockedConfig.FirstRetryCount,
                        //        FirstLockTime = lockedConfig.FirstLockTime
                        //    })
                        //).GetAwaiter().GetResult();
                    }
                    else
                    {
                        lockedMsg=$"输错账号密码次数已达{lockedInfo.RetryCount}次，次数达到{lockedConfig.SecondRetryCount},将锁定{lockedConfig.SecondLockTime}分钟";
                        //lockedMsg = retryCode.EscapeStringAsync(
                        //    null, BunnyParams.FromObject(new
                        //    {
                        //        RetryCount = lockedInfo.RetryCount,
                        //        FirstRetryCount = lockedConfig.SecondRetryCount,
                        //        FirstLockTime = lockedConfig.SecondLockTime
                        //    })
                        //).GetAwaiter().GetResult();
                    }
                }
            }

            var key = GetDataKey(dataKey);

            await RedisHelper.Client.SetAsync(key, lockedInfo, TimeSpan.FromMinutes(lockedConfig.SecondLockTime));

            return (isLocked, lockedMsg);
        }

        /// <summary>
        /// 添加锁定信息，如果满足锁定条件，返回true，并返回锁定信息
        /// </summary>
        /// <param name="dataKey"></param>
        /// <param name="lockedMsg"></param>
        /// <returns></returns>
        /// <exception cref="BusinessException"></exception>
        public bool AddLocked(string dataKey, out string lockedMsg)
        {
            // get config 
            var lockedConfig = _setting.GetSettingValue<LockedConfiguration>(SystemSettingConstants.DataLockedSettingId, SettingTypeEnum.System);

            if (lockedConfig == null)
            {
                throw new BusinessException("未配置账号重试锁定相关配置");
            }

            bool isLocked = false;
            lockedMsg = string.Empty;

            /* if the data is not locked
             * 1. if the data is not locked, add a new locked info
             * 2. if the data is locked, check the retry count
             */
            string retryComment = "输错账号密码次数已达{RetryCount}次，次数达到{FirstRetryCount},将锁定{FirstLockTime}分钟";
            string lockingCommentMin = "账号已被锁定{FirstLockTime}分钟";
            string lockingCommentHour = "账号已被锁定{FirstLockTime}小时";
            string retryCode = "login_err_retry";
            string lockingHourCode = "account_locked_hour";
            string lockingMinCode = "account_locked_min";
            if (!TryGetLocked(dataKey, out var lockedInfo) && lockedInfo == null)
            {
                lockedInfo = new LockedInfo
                {
                    RetryCount = 1,
                    LockEndTime = DateTime.Now,
                    LockedCount = 1
                };

                if (lockedInfo.LockedCount == 1)
                {
                    lockedMsg = $"输错账号密码次数已达{lockedInfo.RetryCount}次，次数达到{lockedConfig.FirstRetryCount},将锁定{lockedConfig.FirstLockTime}分钟";
                    //lockedMsg = retryCode.EscapeStringAsync(
                    //    null, BunnyParams.FromObject(new
                    //    {
                    //        RetryCount = lockedInfo.RetryCount,
                    //        FirstRetryCount = lockedConfig.FirstRetryCount,
                    //        FirstLockTime = lockedConfig.FirstLockTime
                    //    })
                    //).GetAwaiter().GetResult();
                }
                else
                {
                    lockedMsg = $"输错账号密码次数已达{lockedInfo.RetryCount}次，次数达到{lockedConfig.SecondRetryCount},将锁定{lockedConfig.SecondLockTime}分钟";
                    //lockedMsg = retryCode.EscapeStringAsync(
                    //    null, BunnyParams.FromObject(new
                    //    {
                    //        RetryCount = lockedInfo.RetryCount,
                    //        FirstRetryCount = lockedConfig.SecondRetryCount,
                    //        FirstLockTime = lockedConfig.SecondLockTime
                    //    })
                    //).GetAwaiter().GetResult();
                }
            }
            else
            {
                lockedInfo.RetryCount++;
                if (lockedInfo.LockedCount == 1 && lockedInfo.RetryCount >= lockedConfig.FirstRetryCount)
                {
                    lockedInfo.LockEndTime = DateTime.Now.AddMinutes(lockedConfig.FirstLockTime);
                    lockedMsg = $"账号已被锁定{lockedConfig.FirstLockTime}分钟";
                    //lockedMsg = lockingMinCode.EscapeStringAsync(
                    //    null, BunnyParams.FromObject(new
                    //    {
                    //        FirstLockTime = lockedConfig.FirstLockTime
                    //    })
                    //).GetAwaiter().GetResult();
                    lockedInfo.RetryCount = 0;
                    lockedInfo.LockedCount++;
                    isLocked = true;
                }
                else if (lockedInfo.RetryCount >= lockedConfig.SecondRetryCount)
                {
                    var lockedTime = TimeSpan.FromMinutes(lockedConfig.SecondLockTime);
                    lockedInfo.LockEndTime = DateTime.Now.Add(lockedTime);
                    lockedInfo.RetryCount = 0;
                    lockedInfo.LockedCount++;

                    if (lockedConfig.SecondLockTime > 60)
                    {
                         lockedMsg = $"账号已被锁定{lockedConfig.SecondLockTime / 60}小时";
                        //lockedMsg = lockingHourCode.EscapeStringAsync(
                        //    null, BunnyParams.FromObject(new
                        //    {
                        //        FirstLockTime = lockedConfig.SecondLockTime / 60
                        //    })
                        //).GetAwaiter().GetResult();

                    }
                    else
                    {
                         lockedMsg = $"账号已被锁定{lockedConfig.SecondLockTime}分钟";
                        //lockedMsg = lockingMinCode.EscapeStringAsync(
                        //    null, BunnyParams.FromObject(new
                        //    {
                        //        FirstLockTime = lockedConfig.FirstLockTime
                        //    })
                        //).GetAwaiter().GetResult();
                    }
                    isLocked = true;
                }

                if (!isLocked)
                {
                    if (lockedInfo.LockedCount == 1)
                    {
                        lockedMsg=$"输错账号密码次数已达{lockedInfo.RetryCount}次，次数达到{lockedConfig.FirstRetryCount},将锁定{lockedConfig.FirstLockTime}分钟";
                        //lockedMsg = retryCode.EscapeStringAsync(
                        //    null, BunnyParams.FromObject(new
                        //    {
                        //        RetryCount = lockedInfo.RetryCount,
                        //        FirstRetryCount = lockedConfig.FirstRetryCount,
                        //        FirstLockTime = lockedConfig.FirstLockTime
                        //    })
                        //).GetAwaiter().GetResult();
                    }
                    else
                    {
                        lockedMsg=$"输错账号密码次数已达{lockedInfo.RetryCount}次，次数达到{lockedConfig.SecondRetryCount},将锁定{lockedConfig.SecondLockTime}分钟";
                        //lockedMsg = retryCode.EscapeStringAsync(
                        //    null, BunnyParams.FromObject(new
                        //    {
                        //        RetryCount = lockedInfo.RetryCount,
                        //        FirstRetryCount = lockedConfig.SecondRetryCount,
                        //        FirstLockTime = lockedConfig.SecondLockTime
                        //    })
                        //).GetAwaiter().GetResult();
                    }
                }
            }

            var key = GetDataKey(dataKey);
            RedisHelper.Client.Set(key, lockedInfo, TimeSpan.FromMinutes(lockedConfig.SecondLockTime));
            return isLocked;
        }

        public long Unlocked(string dataKey)
        {
            var key = GetDataKey(dataKey);
            return RedisHelper.Client.Del(key);
        }

        private string GetDataKey(string dataKey)
        {
            var key = dataKey.ToLower();
            return $"DataLocked:{key}";
        }
    }
}
